package com.louis.springboot.demo.utils;

import javax.servlet.http.HttpServletRequest;

import jdk.nashorn.internal.ir.ReturnNode;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

import com.louis.springboot.demo.security.JwtAuthenticatioToken;

/**
 * Security相关操作
 * @author Louis
 * @date Jun 29, 2019
 */
public class SecurityUtils {

	/**
	 * 系统登录认证
	 * @param request
	 * @param username
	 * @param password
	 * @param authenticationManager
	 * @return
	 */
	public static JwtAuthenticatioToken login(HttpServletRequest request, String username, String password, AuthenticationManager authenticationManager) {
		JwtAuthenticatioToken token = new JwtAuthenticatioToken(username, password);
		token.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
		// 执行登录认证过程
	    Authentication authentication = authenticationManager.authenticate(token);
	    /*
	    SecurityContextHolder#
	    SecurityContextHolder看名知义，是一个holder,用来hold住SecurityContext实例的。
	    在典型的web应用程序中，用户登录一次，然后由其会话ID标识。
	    服务器缓存持续时间会话的主体信息。在Spring Security中，
	    在请求之间存储SecurityContext的责任落在SecurityContextPersistenceFilter上，
	    默认情况下，该上下文将上下文存储为HTTP请求之间的HttpSession属性。
	    它会为每个请求恢复上下文SecurityContextHolder，并且最重要的是，
	    在请求完成时清除SecurityContextHolder。SecurityContextHolder是一个类，
	    他的功能方法都是静态的（static）。
	    SecurityContextHolder可以设置指定JVM策略（SecurityContext的存储策略），
	    这个策略有三种：
         MODE_THREADLOCAL：SecurityContext 存储在线程中。
         MODE_INHERITABLETHREADLOCAL：SecurityContext 存储在线程中，但子线程可以获取到父线程中的 SecurityContext。
MODE_GLOBAL：SecurityContext 在所有线程中都相同。
SecurityContextHolder默认使用MODE_THREADLOCAL模式，即存储在当前线程中。在spring security应用中，我们通常能看到类似如下的代码：
Copy
 SecurityContextHolder.getContext().setAuthentication(token);
其作用就是存储当前认证信息。
	     */
	    // 认证成功存储认证信息到上下文
	    SecurityContextHolder.getContext().setAuthentication(authentication);
		// 生成令牌并返回给客户端
	    token.setToken(JwtTokenUtils.generateToken(authentication));
		return token;
	}

	/**
	 * 获取令牌进行认证
	 * @param request
	 */
	public static void checkAuthentication(HttpServletRequest request) {
		// 获取令牌并根据令牌获取登录认证信息
		String strURI = request.getRequestURI();

		if (strURI.endsWith("/index"))
		{
			SecurityContextHolder.getContext().setAuthentication(null);
			return;
		}

		Authentication authentication = JwtTokenUtils.
				getAuthenticationeFromToken(request);
		// 设置登录认证信息到上下文

	//	authentication = new JwtAuthenticatioToken("admin", "admin");//null;
		SecurityContextHolder.getContext().setAuthentication(authentication);
	}

	/**
	 * 获取当前用户名
	 * @return
	 */
	public static String getUsername() {
		String username = null;
		Authentication authentication = getAuthentication();
		if(authentication != null) {
			Object principal = authentication.getPrincipal();
			if(principal != null && principal instanceof UserDetails) {
				username = ((UserDetails) principal).getUsername();
			}
		}
		return username;
	}
	
	/**
	 * 获取用户名
	 * @return
	 */
	public static String getUsername(Authentication authentication) {
		String username = null;
		if(authentication != null) {
			Object principal = authentication.getPrincipal();
			if(principal != null && principal instanceof UserDetails) {
				username = ((UserDetails) principal).getUsername();
			}
		}
		return username;
	}
	
	/**
	 * 获取当前登录信息
	 * @return
	 */
	public static Authentication getAuthentication() {
		if(SecurityContextHolder.getContext() == null) {
			return null;
		}
		Authentication authentication = SecurityContextHolder.getContext().
				getAuthentication();

		return authentication;
	}
	
}
